package com.example.edu.Service.Impl;

import cn.hutool.core.util.RandomUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONUtil;
import com.example.edu.Dto.*;
import com.example.edu.Entity.Course;
import com.example.edu.Entity.User;
import com.example.edu.Mapper.*;
import com.example.edu.Service.CourseService;
import com.example.edu.Utils.AIUtil;
import com.example.edu.Utils.CacheDataBaseUtil;
import com.example.edu.Utils.JwtUtil;
import com.zhipu.oapi.Constants;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

import static com.example.edu.Utils.MyConstants.*;

@Service
public class CourseServiceImpl implements CourseService {
    @Resource
    UserMapper userMapper;
    @Resource
    CourseMapper courseMapper;
    @Resource
    ChapterMapper chapterMapper;
    @Resource
    Course_StudentMapper course_studentMapper;
    @Resource
    Course_RecordMapper course_recordMapper;
    @Resource
    CacheDataBaseUtil cacheDataBaseUtil;
    @Resource
    AIUtil aiUtil;
    private static final Logger logger = LoggerFactory.getLogger(ChapterServiceImpl.class);

    @Override
    @Transactional
    public Return create(HttpServletRequest request, CourseCreateDtoG createData) {
        try {
            return create1(request,createData);
        } catch (Exception e){
            return Return.fail(1,"创建失败");
        }
    }

    @Override
    public Return getList(HttpServletRequest request, ListDtoG listData) {
        String token = JwtUtil.getTokenFromCookie(request);
        String telephone = JwtUtil.getUsername(token);
        User user = cacheDataBaseUtil.selectById(USER_KEY,telephone, User.class,telephone2->userMapper.getUser(telephone2),
                USER_CACHE_TTL, TimeUnit.HOURS);
        if(user.getRole() == 0)
            return returnTeacherCourses(user,listData);
        else
            return returnStudentCourses(user.getUser_id(),listData);
    }

    @Override
    @Transactional
    public Return delete(Course courseId) {
        try {
            return delete1(courseId.getCourse_id());
        } catch (Exception e){
            return Return.fail(1,"删除失败");
        }
    }

    @Override
    @Transactional
    public Return update(Course course) {
        try {
            return update1(course);
        } catch (Exception e){
            return Return.fail(1,"修改失败");
        }
    }

    @Async
    @Transactional
    public void createAI(Course course) {
        List<String> user_messages = new ArrayList<>();
        String user_message = String.format(COURSE_AI_COURSE_NAME_FORMAT,course.getCourse_name());
        user_messages.add(user_message);
        List<String> system_messages = new ArrayList<>();
        system_messages.add(SYSTEM_PROMPT1);
        system_messages.add(COURSE_AI_SYSTEM_PROMPT1);
        PromptDto prompt_data = new PromptDto(user_messages,system_messages,course.getCourse_name());
        try {
            String result = aiUtil.getAnswer(prompt_data, 1, Constants.ModelChatGLM4Plus);
            if(result == null)
                return;
            JSONArray jsonArray = JSONUtil.parseArray(result);
            List<CreateCourseAIDto> createCourseAIData = jsonArray.toList(CreateCourseAIDto.class);
            chapterMapper.addChapters(createCourseAIData,course.getCourse_id());
        }catch (Exception e){
            logger.error(e.getMessage());
            throw new RuntimeException(e);
        }
    }

    @Override
    @Transactional
    public Return join(HttpServletRequest httpServletRequest, Course inviteCode) {
        try {
            return join1(httpServletRequest,inviteCode.getInvite_code());
        } catch (Exception e) {
            return Return.fail(2,"加入失败");
        }
    }

    @Override
    @Transactional
    public Return out(HttpServletRequest httpServletRequest, Course courseId) {
        try{
            return out1(httpServletRequest,courseId.getCourse_id());
        } catch (Exception e) {
            return Return.fail(1,"退出失败");
        }
    }

    @Override
    public Return get(Course course) {
        try {
            return Return.ok(courseMapper.getCourse(course.getCourse_id()));
        } catch (Exception e){
            logger.error(e.getMessage());
            return Return.fail(1,"获取失败");
        }
    }

    @Transactional
    public Return create1(HttpServletRequest request, CourseCreateDtoG createData) {
        String token = JwtUtil.getTokenFromCookie(request);
        String telephone = JwtUtil.getUsername(token);
        try {
           User userId = cacheDataBaseUtil.selectById(USER_KEY,telephone, User.class,telephone2->userMapper.getUser(telephone2),
                   USER_CACHE_TTL, TimeUnit.HOURS);
           int course_teacher = userId.getUser_id();
           String course_name = createData.getCourse_name();
           String invite_code = RandomUtil.randomString(12);
           Course course = new Course(course_name,course_teacher,invite_code);
           courseMapper.addCourse(course);
           if(createData.getAuto_chapter() == 1)
               createAI(course);
           return Return.ok(invite_code);
        } catch (Exception e){
            logger.error(e.getMessage());
            throw new RuntimeException(e);
        }
    }

    @Transactional
    public Return delete1(Integer courseId) {
        try {
            courseMapper.delete(courseId);
            return Return.ok();
        } catch (Exception e){
            logger.error(e.getMessage());
            throw new RuntimeException(e);
        }
    }

    @Transactional
    public Return update1(Course course){
        try{
            courseMapper.update(course);
            return Return.ok();
        } catch (Exception e){
            logger.error(e.getMessage());
            throw new RuntimeException(e);
        }
    }

    @Transactional
    public Return join1(HttpServletRequest httpServletRequest, String inviteCode) {
        String token = JwtUtil.getTokenFromCookie(httpServletRequest);
        String telephone = JwtUtil.getUsername(token);
        try{
            User userId = cacheDataBaseUtil.selectById(USER_KEY,telephone, User.class, telephone2->userMapper.getUser(telephone2),
                    USER_CACHE_TTL, TimeUnit.HOURS);
            int student_id = userId.getUser_id();
            Integer course_id = courseMapper.getCourseIdByCode(inviteCode);
            if(course_id == null)
                return Return.fail(1,"不存在的邀请码");
            course_studentMapper.add(course_id,student_id);
            addRecord(course_id,student_id);
            return Return.ok();
        } catch (Exception e){
            logger.error(e.getMessage());
            throw new RuntimeException(e);
        }
    }

    @Transactional
    public Return out1(HttpServletRequest httpServletRequest, Integer courseId) {
        String token = JwtUtil.getTokenFromCookie(httpServletRequest);
        String telephone = JwtUtil.getUsername(token);
        try {
            User userId = cacheDataBaseUtil.selectById(USER_KEY,telephone, User.class, telephone2->userMapper.getUser(telephone2),
                    USER_CACHE_TTL, TimeUnit.HOURS);
            course_studentMapper.delete(courseId,userId.getUser_id());
            deleteRecord(courseId,userId.getUser_id());
            return Return.ok();
        } catch (Exception e){
            logger.error(e.getMessage());
            throw new RuntimeException(e);
        }
    }

    private Return returnTeacherCourses(User user, ListDtoG listData){
        int course_teacher = user.getUser_id();
        int total = courseMapper.getCourseNum(course_teacher);
        if (total == 0)
            return Return.ok("还没有课程",new ListDtoR(total, new ArrayList<>()));
        List<CourseListDtoR> course_list = courseMapper.getCourses(course_teacher,
                listData.getStart_index(), Math.min(listData.getCount(), total - listData.getStart_index()));
        if (course_list == null || course_list.isEmpty())
            return Return.ok("这一页还没有课程",new ListDtoR(total, new ArrayList<>()));
        for (CourseListDtoR courseListDtoR : course_list)
            courseListDtoR.setCourse_teacher(user.getNickname());
        return Return.ok(new ListDtoR(total, course_list));
    }

    private Return returnStudentCourses(int user_id, ListDtoG listData){
        int total = courseMapper.getCourseNum2(user_id);
        if(total == 0)
            return Return.ok("还没有课程",new ListDtoR(total, new ArrayList<>()));
        List<CourseListDtoR> courses = courseMapper.getCourses2(user_id,
                listData.getStart_index(),Math.min(listData.getCount(),total-listData.getStart_index()));
        if(courses.isEmpty())
            return Return.ok("这一页还没有课程",new ListDtoR(total, new ArrayList<>()));
        return Return.ok(new ListDtoR(total,courses));
    }

    @Async
    @Transactional
    void addRecord(int course_id, int student_id){
        List<Integer> days = new ArrayList<>();
        for(int i = 0;i < 7;i++)
            days.add(i);
        try{
            course_recordMapper.add(course_id,student_id,days);
        } catch (Exception e){
            logger.error(e.getMessage());
            throw new RuntimeException(e);
        }
    }

    @Async
    @Transactional
    void deleteRecord(int course_id, int student_id){
        try {
            course_recordMapper.delete(course_id,student_id);
        } catch (Exception e){
            logger.error(e.getMessage());
            throw new RuntimeException(e);
        }
    }
}
